package com.coderman.common.starter.nacos.datajson.service;

import com.alibaba.cloud.nacos.NacosDiscoveryProperties;
import com.coderman.common.starter.nacos.datajson.annotations.ConfigField;
import com.coderman.common.starter.nacos.datajson.annotations.NacosConfig;
import com.coderman.common.starter.nacos.datajson.config.ConfigFieldBean;
import com.coderman.common.starter.nacos.datajson.config.NacosConfigBean;
import com.coderman.common.starter.nacos.datajson.config.NacosDataJsonProperties;
import com.coderman.utils.clazz.ClassUtils;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.stereotype.Service;

import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Description:
 * date: 2020/9/29 9:04 上午
 *
 * @author fanchunshuai
 * @version 1.0.0
 * @since JDK 1.8
 */
@Service
@Configuration
public class MetaDataService {
    /**
     * 指定扫描类路径减少扫描时间
     */
    @Value("{nacos.datajson.entitypath}")
    private String entitypath;

    @Autowired
    private NacosDiscoveryProperties nacosDiscoveryProperties;
    @Autowired
    private NacosDataJsonProperties nacosDataJsonProperties;

    private static List<NacosConfigBean> nacosConfigBeanList = new ArrayList<>();

    public List<NacosConfigBean> getNacosConfigBeanList() {
        return nacosConfigBeanList;
    }


    /**
     * 根据配置的类路径获取配置的entity元数据
     *
     * @return
     */
    public synchronized void scanNacosJSONEntity() throws IllegalAccessException, InstantiationException, ClassNotFoundException {
        List<Class<?>> classList = ClassUtils.getClass(nacosDataJsonProperties.getEntitypath(), true);
        List<NacosConfigBean> list = new ArrayList<>();
        for (Class clazz : classList) {
            NacosConfig nacosConfig = AnnotationUtils.findAnnotation( Class.forName(clazz.getName()),NacosConfig.class);
            if(nacosConfig == null){
                continue;
            }

            NacosConfigBean nacosConfigBean = getBean(clazz,nacosConfig);
            nacosConfigBean.setClazz(clazz);
            List<ConfigFieldBean> configFieldBeanList = getConfigFieldBeanList(clazz);
            nacosConfigBean.setConfigFieldBeanList(configFieldBeanList);
            list.add(nacosConfigBean);
        }
        if(CollectionUtils.isEmpty(nacosConfigBeanList)){
            this.getNacosConfigBeanList().addAll(list);
        }
    }

    /**
     * 获取NacosConfigBean
     * @param clazz
     * @return
     */
    private NacosConfigBean getBean(Class<?> clazz,NacosConfig nacosConfig){

        NacosConfigBean nacosConfigBean = new NacosConfigBean();
        String dataId = nacosConfig.dataId();
        //使用默认方式构造dataId
        if (StringUtils.isEmpty(dataId)) {
            dataId = clazz.getName();
        }
        nacosConfigBean.setDataId(dataId);

        String groupId = nacosConfig.groupId();
        //使用默认方式构造groupId
        if (StringUtils.isEmpty(groupId)) {
            groupId = nacosDiscoveryProperties.getService() + "-" +clazz.getSimpleName();
        }
        nacosConfigBean.setGroupId(groupId);

        String desc = nacosConfig.desc();
        if (StringUtils.isEmpty(desc)) {
            desc = "NacosJSON configService:"+clazz.getSimpleName();
        }
        nacosConfigBean.setDesc(desc);
        nacosConfigBean.setClassSimpleName(clazz.getSimpleName());
        return nacosConfigBean;
    }

    /**
     * 获取getConfigFieldBeanList
     * @param clazz
     * @return
     */
    private List<ConfigFieldBean> getConfigFieldBeanList(Class<?> clazz) throws ClassNotFoundException {
        Field [] fieldArr = Class.forName(clazz.getName()).getDeclaredFields();
        List<ConfigFieldBean> list = new ArrayList<>();

        for (Field field : fieldArr){
            if(!field.isAnnotationPresent(ConfigField.class)){
                continue;
            }
            ConfigField configField = field.getAnnotation(ConfigField.class);
            ConfigFieldBean configFieldBean = new ConfigFieldBean();
            configFieldBean.setFieldName(field.getName());
            configFieldBean.setDesc(configField.desc());
            configFieldBean.setQueryKey(configField.queryKey());
            list.add(configFieldBean);
        }
        return list;
    }

}
